package other.system.client.oa;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.api.annotations.*;
import com.rkhd.platform.sdk.creekflow.approvalevent.ApprovalEventRequest;
import com.rkhd.platform.sdk.data.model.Department;
import com.rkhd.platform.sdk.data.model.Order;
import com.rkhd.platform.sdk.exception.AsyncTaskException;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.exception.XsyHttpException;
import com.rkhd.platform.sdk.http.*;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.model.XObject;
import com.rkhd.platform.sdk.service.FutureTaskService;
import com.rkhd.platform.sdk.task.FutureTask;
import org.apache.commons.lang.StringUtils;
import other.system.client.apitool.OAClientUtils;
import other.system.client.fssc.ContractCompleteSendFssc;
import other.system.client.util.HCDateUtils;
import other.system.client.util.HCXObjectService;
import other.system.client.util.ResultVo;

import java.io.IOException;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: OA对接接口
 * @Author: 黎炎松
 * @Date: 2024/6/25 16:36
 */
@RestApi(baseUrl = "/xsy/oa")
public class OAClientApi implements FutureTask {
    private static HCXObjectService hcxObjectService = new HCXObjectService();
    private static final Logger logger = LoggerFactory.getLogger();
    private static String LOGGER_MSG = "审批模块回写日志 ==> ";

    public static void main(String[] args) throws Exception {
        OAClientApi oaClientApi = new OAClientApi();

        String tempData = "{\"approvalStatus\":5,\"fd_3d7721311858e6\":\"2024-10-31 00:00:00\",\"moduleType\":\"4\",\"oaUrl\":\"https://oa.tcl.com/km/review/km_review_main/kmReviewMain.do?method=view&fdId=192ff933568d7e5a39177f04e2b9f288\",\"approvalLog\":[{\"fdHandleName\":\"周旭东\",\"fdApprove\":\"提交文档\",\"fdNodeId\":\"192ff93395627c7bcf212da40908b062\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdTime\":\"2024-11-06 11:44\",\"fdNodeName\":\"N2 起草节点\",\"fdHandleNo\":\"xudong3.zhou\"},{\"fdFileId\":\"19300ae9efa48e4dbd6918243ef817a3;19300aea64390db495827b24819a89cf\",\"fdHandleName\":\"黄冰冰\",\"fdApprove\":\"通过\",\"fdOpinion\":\"同意，项目已邮件特批\",\"fdNodeId\":\"19300ad8acbc8c1d13dea054a108a3eb\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdFileName\":\"【待特批归档】浙江嘉益-海康AGV驱动轮等易损件备件采购.jpg;回复 【需特批归档的项目】F102242859S-嘉益海康AGV易损件.msg\",\"fdTime\":\"2024-11-06 16:54\",\"fdNodeName\":\"N76 商务专员\",\"fdHandleNo\":\"bingbing.huang\"},{\"fdHandleName\":\"余赟\",\"fdApprove\":\"通过\",\"fdOpinion\":\"同意\",\"fdNodeId\":\"1930432c5ccfaf3338f078f4abc90496\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdTime\":\"2024-11-07 09:17\",\"fdNodeName\":\"N79 交付负责人\",\"fdHandleNo\":\"yun4.yu\"},{\"fdHandleName\":\"余婧\",\"fdApprove\":\"通过\",\"fdOpinion\":\"同意，条款背靠背供应商\",\"fdNodeId\":\"1930469f34aae6d8785914e447d8964a\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdTime\":\"2024-11-07 10:18\",\"fdNodeName\":\"N133 财务经理\",\"fdHandleNo\":\"jing12.yu\"},{\"fdHandleName\":\"王玉芳\",\"fdApprove\":\"通过\",\"fdOpinion\":\"同意\",\"fdNodeId\":\"193046c3e200ec921dceeb147a5b2965\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdTime\":\"2024-11-07 10:24\",\"fdNodeName\":\"N128 法务\",\"fdHandleNo\":\"yufang4.wang\"},{\"fdHandleName\":\"戴海桦\",\"fdApprove\":\"通过\",\"fdOpinion\":\"同意\",\"fdNodeId\":\"19304a26b378ab5d123c474464f9aa88\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdTime\":\"2024-11-07 11:19\",\"fdNodeName\":\"N140 部门负责人\",\"fdHandleNo\":\"frihart.dai\"},{\"fdHandleName\":\"戴海桦\",\"fdApprove\":\"身份重复跳过：“168266338ffd7984c85e7744da3b509e”\",\"fdNodeId\":\"19304a2974cbb5130d3f55b41f9836c4\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdTime\":\"2024-11-07 11:19\",\"fdNodeName\":\"N85 一级部门负责人\",\"fdHandleNo\":\"frihart.dai\"},{\"fdHandleName\":\"黄冰冰\",\"fdApprove\":\"通过\",\"fdOpinion\":\"同意\",\"fdNodeId\":\"19304a2cd018e1029e3458745688f814\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdTime\":\"2024-11-07 11:20\",\"fdNodeName\":\"N94 商务专员盖章\",\"fdHandleNo\":\"bingbing.huang\"},{\"fdFileId\":\"19304a3c2c39b44fcb3fa15495781d59\",\"fdHandleName\":\"黄冰冰\",\"fdApprove\":\"通过\",\"fdOpinion\":\"同意\",\"fdNodeId\":\"19304a341379c3df3f397134f888282a\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdFileName\":\"GCES-2024-1042-01-嘉益海康AGV易损件-20241107.jpg\",\"fdTime\":\"2024-11-07 11:21\",\"fdNodeName\":\"N107 商务归档合同\",\"fdHandleNo\":\"bingbing.huang\"}],\"moduleId\":\"192ff933568d7e5a39177f04e2b9f288\"}";
        //tempData = " {\"approvalStatus\":4,\"moduleType\":\"3\",\"approvalLog\":[{\"fdHandleName\":\"黄华\",\"fdApprove\":\"提交文档\",\"fdNodeId\":\"19286625493d6e03e00faf940dc9cc2f\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdTime\":\"2024-10-13 22:57\",\"fdNodeName\":\"N2 起草节点\",\"fdHandleNo\":\"hua37.huang\"},{\"fdHandleName\":\"任学良\",\"fdApprove\":\"驳回：\\\"type\\\":\\\"node\\\",\\\"def\\\":\\\"起草节点\\\",\\\"value\\\":\\\"N2\\\":[\",\"fdOpinion\":\"驳回原因:胡磊职务确认\",\"fdNodeId\":\"19288c5dda48099066e04094496867a0\",\"fdStatus\":\"1\",\"fd_action_key\":\"通过\",\"fdTime\":\"2024-10-14 10:06\",\"fdNodeName\":\"N144 部门负责人\",\"fdHandleNo\":\"xueliang1.ren\"}],\"moduleId\":\"1928662529ae84a1b5ddacb49ba83d9a\"}";
        //oaClientApi.syncRewriteApprovalInfo(JSONObject.parseObject(tempData));
        //oaClientApi.getApprovalLogStr(null, "192314dca3347c06ad920a146c7a4f0a");

        //oaClientApi.handDeBookingOaCheck(3424723389291138L);

        //oaClientApi.uploadOaFile("192030092743e6cea6083aa4871b3b6b");

        //String updateOrderData2 = "{\"oaUrls__c\":\"https://oa.tcl.com/km/review/km_review_main/kmReviewMain.do?method=view&fdId=1939b22256de821b5d4ac2640cf912a1\",\"oaApprovalStatus__c\":5,\"lockStatus\":2,\"orderSigningDate__c\":\"1733414400000\",\"orderStatus__c\":6,\"id\":3583338769226385}";
        //oaClientApi.updateObjetData(JSONObject.parseObject(updateOrderData2), "order");
    }


    /**
     * 手动模块deBooking审批完成回调，计算deBooking完成金额
     * @param deBookingId
     * @return
     */
    @RestMapping(value = "/handDeBookingOaCheck", method = RequestMethod.POST)
    public ResultVo handDeBookingOaCheck(@RestQueryParam(name = "id") Long deBookingId) throws Exception {
        logger.info(LOGGER_MSG + "手动触发");

        JSONObject updateData = new JSONObject();
        updateData.put("id", deBookingId);
        updateData.put("lockStatus", 2);
        updateData.put("oaApprovalLog__c", "手动调用模拟审批完成回调");
        updateData.put("oaApprovalStatus__c", 5);
        updateObjetData(updateData, "debooking__c");
        calcDeBookingAmount(deBookingId);

        logger.info(LOGGER_MSG + "处理完成");
        return ResultVo.getSuccess("");
    }


    /**
     * 回写模块审批日志、状态信息 （处理为异步处理，因为OA需要等CRM状态返回后才回往下走流程）
     * @param jsonData
     * @return
     */
    @RestMapping(value = "/rewriteApprovalInfo", method = RequestMethod.POST)
    public ResultVo rewriteApprovalInfo(@RestBeanParam(name = "body") JSONObject jsonData) throws AsyncTaskException {
        // 使用异步进行处理
        String messageId = FutureTaskService.instance().addFutureTask(OAClientApi.class, jsonData.toString());
        logger.info("触发异步回写 ==> messageId:" + messageId);
        return ResultVo.getSuccess("");
    }

    /**
     * 执行异步事件
     * @param s
     * @throws ScriptBusinessException
     */
    @Override
    public void execute(String s) throws ScriptBusinessException {
        JSONObject jsonData = JSONObject.parseObject(s, JSONObject.class);
        syncRewriteApprovalInfo(jsonData);
    }

    /**
     * 回写模块审批日志、状态信息
     * @param jsonData
     * @return
     */
    public ResultVo syncRewriteApprovalInfo(JSONObject jsonData) {
        try {
            logger.info(LOGGER_MSG + "回传的数据 = " + jsonData);
            // 获取数据
            /*
                moduleType
                    1.销售类盖章申请-报价单
                    2.销售类盖章申请-投标盖章类文件
                    3.销售类盖章申请-其他销售类文件
                    4.销售合同评审
                    5.零星采购
                    6.市场活动
                approvalStatus
                   1.提交 2.撤回 3.审批 4.驳回 5.审批结束 6.作废
                moduleId
                    用于驳回后重新提交回到原流程，OA的ID
                approvalLog
                     审批日志数据
             */
            Integer moduleType = jsonData.getInteger("moduleType");
            String moduleId = jsonData.getString("moduleId");
            List<JSONObject> approvalLogList = JSONArray.parseArray(jsonData.getString("approvalLog"), JSONObject.class);
            Integer approvalStatus = jsonData.getInteger("approvalStatus");
            logger.info(LOGGER_MSG + " moduleType = " + moduleType);
            logger.info(LOGGER_MSG + " moduleId = " + moduleId);
            // 解决OA回调时间间隔短状态更新问题，如果是审批通过则延迟执行，否则状态会出现覆盖更新为审批中的情况
            if (approvalStatus == 5) {
                Thread.sleep(2500);
            }

            // 判断是那个模块
            String objKey = "quote";
            String fieldStr = ""; // 合同需要多查询一号订单，用于后面操作
            switch (moduleType) {
                case 1:
                    objKey = "quote";
                    break;
                case 2:
                    objKey = "bidSeal__c";
                    break;
                case 3:
                    objKey = "customEntity39__c";
                    break;
                case 4:
                    objKey = "contract";
                    fieldStr = ",order1__c,entityType,status ";
                    break;
                case 5:
                    objKey = "sporadicProcurement__c";
                    break;
                case 6:
                    objKey = "campaign";
                    break;
            }

            String sql = String.format("select id%s from %s where oaApprovalId__c = '%s' ", fieldStr, objKey, moduleId);
            XObject approvalObj = hcxObjectService.queryOne(sql, XObject.class);

            logger.info(LOGGER_MSG + "approvalObj:" + approvalObj);
            if (approvalObj == null) {

                // 如果是合同模块，再需要对订单、deBooking进行查询
                boolean returnTips = true;
                if (moduleType == 4) {
                    // 订单查询
                    sql = String.format("select id,orderStatus__c from _order where oaApprovalId__c = '%s'", moduleId);
                    approvalObj = hcxObjectService.queryOne(sql, XObject.class);
                    if (approvalObj != null) {
                        objKey = "order";
                        returnTips = false;
                    }

                    // deBooking查询
                    if (approvalObj == null) {
                        sql = String.format("select id from debooking__c where oaApprovalId__c = '%s'", moduleId);
                        approvalObj = hcxObjectService.queryOne(sql, XObject.class);
                        if (approvalObj != null) {
                            objKey = "debooking__c";
                            returnTips = false;
                        }
                    }
                }

                if (returnTips) {
                    logger.error(LOGGER_MSG + "查询不到关联的数据 moduleId: " + moduleId);
                    // 可能会存在首次因为数据还未保存好 OA就立马进行回写所以不进行报错提示否则OA会显示异常(因为是全量，所以可以等后面的审批操作在进行回写审批日志)
                    //return ResultVo.getFail("查询不到关联的数据 moduleId: " + moduleId);
                    return ResultVo.getSuccess("");
                }
            }


            // 更新主表数据数据
            logger.info(LOGGER_MSG + "objKey = " + objKey);
            Long dataId = approvalObj.getAttribute("id");
            JSONObject updateData = new JSONObject();
            updateData.put("id", dataId);
            updateData.put("lockStatus", 2);
            updateData.put("oaApprovalLog__c", getApprovalLogStr(approvalLogList, moduleId, approvalStatus));
            updateData.put("oaApprovalStatus__c", approvalStatus);
            // 是否解锁
            List<Integer> unlockStatusList = Arrays.asList(2, 4, 6);
            if (unlockStatusList.contains(approvalStatus)) {
                updateData.put("lockStatus", 1);
            }
            // 合同和订单需要修改数据状态 + 需要判断当前状态不是归档，如果是归档就不进行更新
            String statusKey = objKey.equals("contract") ? "status" : "orderStatus__c";
            Object orderStatus = approvalObj.getAttribute(statusKey);
            if ((objKey.equals("contract") || objKey.equals("order"))) {
                if (!Objects.equals(orderStatus, 2)) {
                    updateData.put(statusKey, getDataStatus(objKey, approvalStatus));
                }

                // 签署日 oaUrl
                updateData.put("oaUrls__c", jsonData.getString("oaUrl"));
                String signDate = jsonData.getString("fd_3d7721311858e6");
                if (StringUtils.isNotBlank(signDate)) {
                    String signDateKey = objKey.equals("contract") ? "signDate" : "orderSigningDate__c";
                    updateData.put(signDateKey, HCDateUtils.stringToLong(signDate, HCDateUtils.FORMATTIME));
                }
            }
            updateObjetData(updateData, objKey);


            // 如果是合同，需要修改1号订单的状态
            Long orderId = approvalObj.getAttribute("order1__c");
            if (objKey.equals("contract") && orderId != null) {
                logger.info(LOGGER_MSG + "合同修改1号订单状态");
                JSONObject updateOrderData = new JSONObject();
                updateOrderData.put("id", orderId);
                updateOrderData.put("lockStatus", 1);
                updateOrderData.put("oaUrls__c", jsonData.getString("oaUrl"));

                // 需要获取1号订单的当前状态
                sql = String.format("select id,orderStatus__c from _order where  id = %s", orderId);
                XObject xObject = hcxObjectService.queryOne(sql, XObject.class);
                Integer oneOrderStatus = xObject.getAttribute("orderStatus__c");
                if (!Objects.equals(oneOrderStatus, 2)) {
                    updateOrderData.put("orderStatus__c", getDataStatus("order", approvalStatus));
                }

                // 更新1号订单的订单签署日
                String signDate = jsonData.getString("fd_3d7721311858e6");
                if (StringUtils.isNotBlank(signDate)) {
                    updateOrderData.put("orderSigningDate__c", HCDateUtils.stringToLong(signDate, HCDateUtils.FORMATTIME));
                }

                // 如果是完成 需要把1号订单锁定
                if (approvalStatus == 5) {
                    updateOrderData.put("lockStatus", 2);
                    updateOrderData.put("oaApprovalStatus__c", approvalStatus); // 同步OA审批状态
                }
                logger.info(LOGGER_MSG + "updateOrderData: " + updateOrderData);
                updateObjetData(updateOrderData, "order");
            }


            // 审批完成
            if (approvalStatus == 5) {
                logger.info(LOGGER_MSG + " OA审批通过");

                // 处理OA审批返回的附件字段
                dealOaApprovalFile(objKey, approvalObj, approvalLogList);

                if (objKey.equals("debooking__c")) {

                    // 如果是deBooking且回写状态是审批完成，则需要触发deBooking金额计算
                    calcDeBookingAmount(dataId);
                } else if (objKey.equals("contract")) {

                    // 合同审批通过推送 FSSC 客户数据
                    ContractCompleteSendFssc contractCompleteSendFssc = new ContractCompleteSendFssc();
                    ApprovalEventRequest request = new ApprovalEventRequest();
                    request.setDataId(dataId);
                    contractCompleteSendFssc.execute(request);

                    // 推送1号订单到PMS
                    if (orderId != null) {
                        logger.info(LOGGER_MSG + " 推送到PMS");
                        // 等触发规则处理完 防止数据查询延迟
                        Thread.sleep(5000);
                        pushOrderToPms(orderId);
                    }

                } else if (objKey.equals("order")) {
                    // 推送订单数据到PMS 等触发规则处理完 防止数据查询延迟
                    Thread.sleep(5000);
                    pushOrderToPms(dataId);
                }
            }

            logger.info(LOGGER_MSG + "回写数据成功");
            return ResultVo.getSuccess("");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(LOGGER_MSG + "回写模块审批数据异常:" + e.getMessage());
            return ResultVo.getFail("回写模块审批数据异常: " + e.getMessage());
        }
    }

    /**
     * 处理OA回传的CRM附件 id, 进行保存
     * @param objKey
     * @param approvalObj
     * @param approvalLogList
     * @throws Exception
     */
    public void dealOaApprovalFile(String objKey, XObject approvalObj, List<JSONObject> approvalLogList) throws Exception {
        logger.info("处理OA返回的附件 ==> 处理开始");

        // 需要处理的对象 合同、订单、deBooking
        if (!Arrays.asList("contract", "order", "debooking__c").contains(objKey)) {
            logger.info("处理OA返回的附件 ==> 当前模块无需处理");
            return;
        }

        // 判断日志文件是否有要处理的附件
        if (approvalLogList == null || approvalLogList.size() <= 0) {
            logger.info("处理OA返回的附件 ==> 审批日志为空");
            return;
        }
        String fdFiles = approvalLogList.stream().filter(v -> v.getString("newFileId") != null).map(v -> v.getString("newFileId")).collect(Collectors.joining(","));
        logger.info("处理OA返回的附件 ==> fdFiles " + fdFiles);
        if (StringUtils.isBlank(fdFiles)) {
            logger.info("处理OA返回的附件 ==> 当前审批日志中没有附件，无需处理");
            return;
        }

        // 获取更新的参数
        Long dataId = approvalObj.getAttribute("id"); // 对象 id
        String factObjKey = objKey; // 实际修改的对象

        // 如果是合同且类型是非 销售其他类合同 (非标其他协议) 则把附件保存在订单上
        Long entityType = approvalObj.getAttribute("entityType"); // 销售其他类合同 (非标其他协议)
        if (objKey.equals("contract") && !Objects.equals(entityType, 3373868832348783L)) {
            factObjKey = "order";
            dataId = approvalObj.getAttribute("order1__c");
        }

        // 获取保存的数据格式
        String[] fileIdList = StringUtils.split(fdFiles, ",");
        List<Map> fileList = new ArrayList<>();
        for (String fileId : fileIdList) {
            Map mapHashMap = new HashMap<>();
            mapHashMap.put("id", fileId);
            fileList.add(mapHashMap);
        }
        logger.info("处理OA返回的附件 ==> fileList " + fileList);

        // 保存数据 订单是扫描件 其他对象是OA审批附件
        logger.info("处理OA返回的附件 ==> 实际保存的对象: " + factObjKey);
        JSONObject updateObjData = new JSONObject();
        updateObjData.put("id", dataId);
        updateObjData.put("oaApprovalFile__c", fileList);
        updateObjetData(updateObjData, factObjKey);
    }


    /**
     * 发送请求，调用自定义接口计算deBooking相关金额
     * @param deBookingId
     * @throws IOException
     * @throws XsyHttpException
     */
    public void calcDeBookingAmount(Long deBookingId) throws IOException, XsyHttpException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sceneType", 1);
        jsonObject.put("fromApproval", 1);
        jsonObject.put("deBookingId", deBookingId);
        jsonObject.put("isCalcOrderBookingAmount", "1"); // 计算订单上的booking金额

        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("POST");
        data.setCallString("/rest/data/v2.0/scripts/api/pass/receivable/calcDeBookingAmount");
        data.setBody(jsonObject.toJSONString());
        JSONObject result = RkhdHttpClient.instance().execute(data, JSONObject::parseObject);
        logger.debug("发送pass自定义请求：" + result);
        if (result.getInteger("code") != 200) {
            logger.error("计算deBooking金额异常: " + result.getString("msg"));
        }
    }

    /**
     * 发送请求，调用自定义接口推送到PMS
     * @param orderId
     * @throws IOException
     * @throws XsyHttpException
     */
    public void pushOrderToPms(Long orderId) throws IOException, XsyHttpException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", orderId);

        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("POST");
        data.setCallString("/rest/data/v2.0/scripts/api/pms/pushPmsOrderData?id=" + orderId);
        data.setBody(jsonObject.toJSONString());
        JSONObject result = RkhdHttpClient.instance().execute(data, JSONObject::parseObject);
        logger.debug("发送pass自定义请求：" + result);
        if (result.getInteger("code") != 0) {
            logger.error("推送订单数据到PMS: " + result.getString("msg"));
        }
    }

    /**
     * 获取合同、订单对应的状态
     * @return
     */
    public Integer getDataStatus(String objKey, Integer approvalStatus) {
        /*
            判断是否是合同、或者订单 需要更新合同的状态、订单的状态
            1.提交 2.撤回 3.审批 4.驳回 5.审批结束 6.作废
            CRM  ==>  合同、订单状态 （订单状态中的审批通过、审批拒绝与合同刚好相反）
            提交 1 ==> 审批中  4
            撤回 2 ==> 草稿 1
            审批中 3 ==> 审批中 4
            驳回 4 ==> 审批拒绝 6
            审批结束 5 ==> 审批通过 5  锁定1号订单
         */
        // value 第一个对应合同状态，第二个对应订单状态
        Map<Integer, int[]> statusTransMap = new HashMap<Integer, int[]>(){{
            put(1, new int[]{4, 4});
            put(2, new int[]{1, 1});
            put(3, new int[]{4, 4});
            put(4, new int[]{6, 5});
            put(5, new int[]{5, 6});
        }};
        int[] statusArr = statusTransMap.get(approvalStatus);
        return objKey.equals("contract") ? statusArr[0] : statusArr[1];
    }

    /**
     * 获取申报日志字符串数据 （兼容移动端只能使用 \n \t ）
     *
     * @param approvalLogList
     * @param approvalStatus
     * @return
     */
    public String getApprovalLogStr(List<JSONObject> approvalLogList, String moduleId, Integer approvalStatus) throws ParseException, InterruptedException {
        String logDataStr = "";

        // 判断是否有值
        if (approvalLogList == null || approvalLogList.size() <= 0) {
            return "暂无审批数据~";
        }

        // 获取当前节点的审批数据
        if (approvalStatus != 5) {
            String encodedString = Base64.getEncoder().encodeToString("crm:crm123456".getBytes());
            CommonData build = CommonData.newBuilder().callString(OAClientUtils.GET_CURRENT_NODE + moduleId)
                    .callType("POST")
                    .header("Authorization", "Basic " + encodedString).build();
            logger.info("延迟2s再去查询当前节点，否则会有延迟的情况: " + System.currentTimeMillis());
            Thread.sleep(2000);
            logger.info("延迟2s再去查询当前节点，否则会有延迟s的情况: " + System.currentTimeMillis());
            String result = CommonHttpClient.instance(20000, 20000).execute(build).getResult();
            logger.info("currentNode: " + result);
            // 头部增加当前审批节点信息 流程节点、处理人、处理状态、到达该节点的时间s
            if (!result.equals("{}")) {
                JSONObject currentNode = JSONObject.parseObject(result, JSONObject.class);

                //Date date = HCDateUtils.stringToDate(currentNode.getString("time"), "yyyy-MM-DD HH:mm:ss");
                //String time = HCDateUtils.dateToString(date, "yyyy-MM-dd HH:mm");

                String time = currentNode.getString("time");

                logDataStr = "当前审批节点" +
                        "\n流程节点: " + currentNode.getOrDefault("nodeName", "") +
                        "\n处理人: " + currentNode.getOrDefault("fdName", "") +
                        "\n到达该节点的时间：" + time +
                        "\n\n";
            }
        } else {
            // OA到审批后面一步会进行连续发送两次回写，所以需要同步保持延迟，否则会导致最终保存的状态是 审核中
            Thread.sleep(2500);
        }

        // 拼接表格数据
        for (int i = 0; i < approvalLogList.size(); i++) {
            JSONObject jsonObject = approvalLogList.get(i);
            String fdOpinion = jsonObject.getString("fdOpinion");
            if (i > 0) {
                logDataStr += "\n\n";
            }
            logDataStr += "序号: " + (i + 1) +
                    "\n流程节点: " + jsonObject.getOrDefault("fdNodeName", "") +
                    "\n处理人: " + jsonObject.getOrDefault("fdHandleName", "") +
                    "\n处理状态：" + jsonObject.getOrDefault("fdApprove", "") +
                    "\n处理时间：" + jsonObject.getOrDefault("fdTime", "") +
                    "\n处理意见：" + (fdOpinion == null ? "" : fdOpinion);
        }
        return logDataStr;
    }


    /**
     * 获取字符串表格数据
     * @param approvalLog
     * @return
     */
    public String getTableDataStr(JSONArray approvalLog) {

        // 判断是否有值
        if (approvalLog == null || approvalLog.size() <= 0) {
            return "暂无审批数据~";
        }

        // 拼接表格数据
        String tdDataStr = "";
        for (int i = 0; i < approvalLog.size(); i++) {
            JSONObject jsonObject = approvalLog.getJSONObject(i);
            String fdOpinion = jsonObject.getString("fdOpinion");
            tdDataStr += "<tr align=\"center\">" +
                    "<td> " + (i + 1) + " </td>" +
                    "<td>" + jsonObject.getOrDefault("fdNodeName", "") + "</td>" +
                    "<td>" + jsonObject.getOrDefault("fdHandleName", "") + "</td>" +
                    "<td>" + jsonObject.getOrDefault("fdApprove", "") + "</td>" +
                    "<td>" + jsonObject.getOrDefault("fdTime", "") + "</td>" +
                    "<td>" + (fdOpinion == null ? "" : fdOpinion) + "</td>" +
                    "</tr>";
        }

        String tableStr = "<div style=\"width: 100%;\"><table align=\"center\" border=\"1\" style=\"width: 100%;border-color: #f4f5f6;\" cellpadding=\"10\" cellspacing=\"0\">" +
                "<tr align=\"center\" style=\"background-color: #e3f0ff;\">" +
                "<th width=\"50\">序号</th>" +
                "<th>流程节点</th>" +
                "<th>处理人</th>" +
                "<th>处理状态</th>" +
                "<th width=\"140\">处理时间</th>" +
                "<th>处理意见</th>" +
                "</tr>" +
                tdDataStr +
                "</table></div>";

        return tableStr;
    }

    /**
     * 更新对象数据
     * @param updateData
     * @param apiKey
     * @throws Exception
     */
    public void updateObjetData(JSONObject updateData,String apiKey) throws Exception {
        logger.info("apiKey：" + apiKey);
        logger.info("需要更新的数据：" + updateData.toString());
        JSONObject params = new JSONObject();
        params.put("data", updateData);
        Long id = updateData.getLong("id");
        RkhdHttpClient httpClient = new RkhdHttpClient();
        RkhdHttpData data  = RkhdHttpData.newBuilder()
                .callType("PATCH")
                .callString("/rest/data/v2.0/xobjects/"+apiKey+"/"+id)
                .header("xsy-criteria", "10")
                .body(params.toJSONString())
                .build();
        String execute = httpClient.execute(data, e -> e);
        JSONObject result = JSONObject.parseObject(execute);
        logger.info("更新结果：" + result);
        if(result.getInteger("code") != 200){
            throw new RuntimeException(result.getString("msg"));
        }
    }



    /**
     * 上传OA文件 （使用系统的 downBlob 文件最大只支持5M）
     * @param fileId
     * @return
     * @throws Exception
     */
    public List uploadOaFile(String fileId) throws Exception{
        logger.debug("文件上传 ==> 开始处理" );
        List<Map> fileList = new ArrayList<>();

        // 获取文件请求链接
        String encodedString = Base64.getEncoder().encodeToString("crm:crm123456".getBytes());
        CommonData getData = CommonData.newBuilder().callString(OAClientUtils.GET_FILE_URL + fileId).callType("POST")
                .header("Cache-Control", "no-cache")
                .header("Authorization", "Basic " + encodedString)
                .build();
        String reqFileUrl = CommonHttpClient.instance().execute(getData).getResult();
        logger.debug("文件上传 ==> reqFileUrl: " + reqFileUrl);

        // 获取文件流
        CommonData data = CommonData.newBuilder().callString(reqFileUrl).callType("GET").build();
        RkhdBlob blob = CommonHttpClient.instance().downBlob(data);

        // 对文件名乱码处理
        String fileName = new String(blob.getFileName().getBytes("ISO-8859-1"), "UTF-8");
        blob.setFileName(fileName);

        // 上传到CRM文件服务器
        Map<String,Object> map = new HashMap<>();
        map.put("files", blob);
        map.put("isImage", false);
        map.put("needFileId", true);
        RkhdHttpData httpData = RkhdHttpData.newBuilder()
                .callString("/rest/file/v2.0/file/batch")
                .callType("POST")
                .header("Content-Type", "multipart/form-data")
                .formData(map)
                .build();
        JSONObject res = RkhdHttpClient.instance().execute(httpData, JSONObject::parseObject);
        logger.debug("文件上传 ==> 返回数据: " + res);
        if (Objects.equals(res.getInteger("code"), 200)) {
            fileList = JSONArray.parseArray(res.getString("result"), Map.class);
        }
        return fileList;
    }



}
